package com.hj.quartz.common.manager;

import com.hj.common.exception.BusinessException;
import com.hj.common.pojo.model.AjaxResult;
import com.hj.quartz.common.constants.ScheduleConstants;
import com.hj.quartz.common.job.BanConcurrentJob;
import com.hj.quartz.common.job.ConcurrentJob;
import com.hj.quartz.common.pojo.entity.JobQuartz;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * job任务调度类
 */
@Component
public class QuartzManager {

    @Autowired
    private Scheduler scheduler;

    /**
     * 得到quartz任务类
     *
     * @param jobQuartz 执行计划
     * @return 具体执行任务类
     */
    private static Class<? extends Job> getQuartzJobClass(JobQuartz jobQuartz) {
        //判断是否并发执行 0 是  1 否
        return "0".equals(jobQuartz.getConcurrent()) ? ConcurrentJob.class : BanConcurrentJob.class;
    }

    /**
     * 构建任务触发对象
     */
    public static TriggerKey getTriggerKey(Integer jobId, String jobGroup) {
        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
    }

    /**
     * 构建任务键对象
     */
    public static JobKey getJobKey(Integer jobId, String jobGroup) {
        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
    }

    /**
     * 添加job信息
     *
     * @param jobQuartz
     * @return
     */
    public void addJob(JobQuartz jobQuartz) {
        try {
            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getQuartzJobClass(jobQuartz)) // 具体执行的业务类
                    .withIdentity(getJobKey(jobQuartz.getId(), jobQuartz.getJobGroup())) // job执行的id
                    .build();
            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobQuartz.getCronExpression());

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(jobQuartz.getId(), jobQuartz.getJobGroup()))//triggerId
                    .withSchedule(scheduleBuilder)
                    .build();

            // 放入参数，运行时的方法可以获取
            jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, jobQuartz);

            // 判断是否存在
            if (scheduler.checkExists(getJobKey(jobQuartz.getId(), jobQuartz.getJobGroup()))) {
                // 防止创建时存在数据问题 先移除，然后在执行创建操作
                scheduler.deleteJob(getJobKey(jobQuartz.getId(), jobQuartz.getJobGroup()));
            }

            //关联job信息和trigger
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动调度器
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new BusinessException("quartz任务添加失败");
        }
    }

    /**
     * 暂停任务
     *
     * @param jobId
     * @param jobGroupName
     * @return
     */
    public void pauseJob(Integer jobId, String jobGroupName) throws SchedulerException {
        scheduler.pauseJob(getJobKey(jobId, jobGroupName));
    }

    /**
     * 恢复任务
     *
     * @param jobId
     * @param jobGroupName
     * @return
     */
    public void resumeJob(Integer jobId, String jobGroupName) throws SchedulerException {
        scheduler.resumeJob(getJobKey(jobId, jobGroupName));
    }

    /**
     * 更新任务
     *
     * @param jobId
     * @param triggerGroupName
     * @param cronExpression
     * @return
     */
    public void rescheduleJob(JobQuartz jobQuartz) throws SchedulerException {
        JobKey jobKey = getJobKey(jobQuartz.getId(), jobQuartz.getJobGroup());
        if (scheduler.checkExists(jobKey)) {
            //删除job任务
            scheduler.deleteJob(jobKey);
        }
        addJob(jobQuartz);
    }

    /**
     * 立即运行任务
     *
     * @param job 调度信息
     */
    @Transactional
    public void run(JobQuartz jobQuartz) throws SchedulerException {
        // 参数
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstants.TASK_PROPERTIES, jobQuartz);
        scheduler.triggerJob(getJobKey(jobQuartz.getId(), jobQuartz.getJobGroup()), dataMap);
    }

    /**
     * 删除定时任务
     *
     * @param jobId
     * @param jobGroupName
     * @return
     */
    public void deleteJob(Integer jobId, String jobGroupName) {
        try {
            scheduler.pauseTrigger(getTriggerKey(jobId, jobGroupName));
            scheduler.unscheduleJob(getTriggerKey(jobId, jobGroupName));
            scheduler.deleteJob(getJobKey(jobId, jobGroupName));
        } catch (SchedulerException e) {
            throw new BusinessException("删除定时任务失败");
        }
    }


    public void clear() throws SchedulerException {
        scheduler.clear();
    }
}
